﻿#define  _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>

//操作符详解


//算数操作符
// +    -   *   /   %
//1. 除了 % 操作符之外，其他的几个操作符可以作用于整数和浮点数。
//2. 对于 / 操作符如果两个操作数都为整数，执行整数除法。而只要有浮点数执行的就是浮点数除法。
//3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。


//移位操作符                            移位操作符，移动的是二进制位
//<< 左移操作符
//>> 右移操作符
//注：移位操作符的操作数只能是整数

//整数的二进制表示有3种
//原码
//反码
//补码

//正的整数的原码、反码、补码相同
//负的整数的原码、反码、补码是要计算的

//7
//00000000000000000000000000000111 - 原码
//00000000000000000000000000000111 - 反码
//00000000000000000000000000000111 - 补码

//-7
//10000000000000000000000000000111 - 原码
//11111111111111111111111111111000 - 反码（原码的符号位不变，其他位按位取反就是反码）
//11111111111111111111111111111001 - 补码（反码+1就是补码）

//整数在内存中存储的是补码

//int main()
//{
//	int a = 7;                                  //7 的补码  00000000000000000000000000000111
//	//左移操作符         左边抛弃、右边补0     //左移操作符后  00000000000000000000000000001110
//	//移动的是二进制位
//	int b = a << 1;
//
//	printf("a = %d\n", a);  //a自身不发生变化
//	printf("b = %d\n", b);  //14
//
//	return 0;
//}


//int main()
//{
//	int a =-7;                                 //-7 的补码  11111111111111111111111111111001
//	//左移操作符         左边抛弃、右边补0     //左移操作符后  11111111111111111111111111110010
//	//移动的是二进制位                              反码 ->  11111111111111111111111111110001
//	int b = a << 1;                           //   原码 ->  10000000000000000000000000001110  
//
//	printf("a = %d\n", a);  //a自身不发生变化
//	printf("b = %d\n", b);  //-14
//
//	return 0;
//}

//右移操作符
//算术移位
//左边用原该值的符号位填充，右边丢弃
//逻辑移位
//左边用0填充，右边丢弃

//int main()
//{
//	int a = 7;                    //7 的补码  00000000000000000000000000000111
//	int b = a >> 1;           //右移操作符后   00000000000000000000000000000011
//	printf("a = %d\n", a);
//	printf("b = %d\n", b);
//
//	return 0;
//}

/*int main()
{
	int a =-7;                    //-7 的补码  11111111111111111111111111111001
	int b = a >> 1;           //算数移位后     11111111111111111111111111111100
	printf("a = %d\n", a);     //反码 ->       11111111111111111111111111111011
	printf("b = %d\n", b);     //原码 ->       10000000000000000000000000000100     -4
	//结果为-4，所以vs2022编译器采用的算数右移
	//算数右移还是逻辑右移取决于编译器
	return 0;                     //-7 的补码  11111111111111111111111111111001
}*/                              //逻辑移位后    01111111111111111111111111111100
              //正整数的原码反码补码相同   ->   01111111111111111111111111111100      2,147,483,644

//对于移位运算符，不要移动负数位，这个是标准未定义的。


//位操作符
//& //按（2进制）位与
//| //按（2进制）位或
//^ //按（2进制）位异或
//注：他们的操作数必须是整数。

//int main()
//{
//	int a = 3;
//	int b = -5;
//	int c = a & b;
//	//100000000000000000000000000000101
//	//111111111111111111111111111111010
//	//111111111111111111111111111111011   - -5的补码
//	//000000000000000000000000000000011   - 3的补码
//	//000000000000000000000000000000011   - 按位与的补码
//	//只要有0就是0，同时为1才是1
//
//	printf("c = %d\n", c);//3
//
//	return 0;
//}

//int main()
//{
//	int a = 3;
//	int b = -5;
//	int c = a | b;
//	//100000000000000000000000000000101   - -5的原码
//	//111111111111111111111111111111010   - -5的反码
//	//111111111111111111111111111111011   - -5的补码
//	//000000000000000000000000000000011   - 3的补码
//	//111111111111111111111111111111011   - 按位或后的补码
//	//111111111111111111111111111111010   - 按位或后的反码
//	//100000000000000000000000000000101   - 按位或后的原码
//	//只要有1就是1，同时为0才是0
//
//	printf("c = %d\n", c);//-5
//
//	return 0;
//}

//int main()
//{
//	int a = 3;
//	int b = -5;
//	int c = a ^ b;
//	//100000000000000000000000000000101   - -5的原码
//	//111111111111111111111111111111010   - -5的反码
//	//111111111111111111111111111111011   - -5的补码
//	//000000000000000000000000000000011   - 3的补码
//	//111111111111111111111111111111000   - 按位异或后的补码
//	//111111111111111111111111111110111   - 按位异或后的反码
//	//100000000000000000000000000001000   - 按位异或后的原码  -8
//	//相同为0，相异为1
//
//	printf("c = %d\n", c);//-8
//
//	return 0;
//}



//不能创建临时变量（第三个变量），实现两个数的交换。

//int main()
//{
//	int a = 3;
//	int b = 5;
//	printf("a=%d,b=%d\n", a, b);
//
//	a = a + b;         //溢出的问题，int有上限，若是a，b没有超过上限，但是a+b超过了上限就无法完成
//	b = a - b;
//	a = a - b;
//	printf("a=%d,b=%d\n", a, b);
//
//	return 0;
//}

//3^3 = 0 -> a^a = 0
//011
//011
//000
//0^5 = 5 -> 0^a = a
//000
//101
//101

//3^3^5 = 5
//3^5^3 = 5
//异或操作符支持交换律
//011
//101
//110
//011
//101

//int main()
//{
//	int a = 3;
//	int b = 5;
//	printf("交换前：a=%d,b=%d\n", a, b);
//
//	a = a ^ b;//a=3^5
//	b = a ^ b;//b=3^5^5=3
//	a = a ^ b;//a=3^5^3=5
//
//	printf("交换后：a=%d,b=%d\n", a, b);
//
//	return 0;
//}

//编写代码实现：求一个整数存储在内存中的二进制中1的个数。
//求补码的二进制中1的个数

//int a = 3;
//00000000000000000000000000000011

//a&1
//00000000000000000000000000000011
//00000000000000000000000000000001
//00000000000000000000000000000001

//int main()
//{
//	int a = -7;
//	int n = 0;
//	int count = 0;
//
//	for (n = 0; n < 32; n++)
//	{
//		int ret = a & 1;//最后一位是1的话ret = 1
//		if (ret == 1)
//		{
//			count++;//当a的补码的最后一位==1时，count+1
//		}
//		a = a >> 1;//a的补码右移一位
//	}
//	printf("二进制中1的个数是：%d\n", count);
//
//	return 0;
//}


//赋值操作符

//单目操作符 
//!			  逻辑反操作
//-			  负值
//+			  正值
//&			  取地址
//sizeof      操作数的类型长度（以字节为单位）
//~           对一个数的二进制按位取反
//--          前置、后置--
//++          前置、后置++
//*           间接访问操作符(解引用操作符)
//(类型)      强制类型转换

//int main()
//{
//	//int a = 0;
//	////~是按二进制位取反
//	////00000000000000000000000000000000 - 补码
//	////11111111111111111111111111111111 -> ~a
//	////11111111111111111111111111111110
//	////10000000000000000000000000000001
//	////-1 
//	//printf("%d\n", ~a);
//
//	//int a = 3;
//	////00000000000000000000000000000011
//	////11111111111111111111111111111100
//	////11111111111111111111111111111011
//	////10000000000000000000000000000100
//	////-4
//	//printf("%d\n", ~a);
//
//	int a = 13;
//	a |= (1 << 4);
//	printf("%d\n", a);//a = 29
//	a &= (~(1 << 4));
//	printf("%d\n", a);//a = 13
//
//	//00000000000000000000000000001101
//	//00000000000000000000000000010000   |
//	//00000000000000000000000000011101 //29 
//	//11111111111111111111111111101111   &
//	//00000000000000000000000000010000  （1<<4）按位取反得到上边
//	//00000000000000000000000000001101 //13
//	return 0;
//}